package cn.jsj.onclock.service.impl;

import cn.jsj.onclock.dao.ClockDao;
import cn.jsj.onclock.dao.LabelDao;
import cn.jsj.onclock.dao.TaskDao;
import cn.jsj.onclock.exception.CustomException;
import cn.jsj.onclock.pojo.ClockEnt;
import cn.jsj.onclock.pojo.LabelEnt;
import cn.jsj.onclock.pojo.TaskEnt;
import cn.jsj.onclock.pojo.identity.ClockStatusEnum;
import cn.jsj.onclock.service.ClockService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.LinkedList;
import java.util.List;

/**
 * @author 卢斌
 */
@Service
public class ClockServiceImpl implements ClockService {

    private final ClockDao clockDao;

    private final TaskDao taskDao;

    private final LabelDao labelDao;

    @Autowired
    public ClockServiceImpl(ClockDao clockDao, LabelDao labelDao, TaskDao taskDao) {
        this.clockDao = clockDao;
        this.labelDao = labelDao;
        this.taskDao = taskDao;
    }

    /**
     * 用户打卡
     *
     * 本接口既可以进行签到打卡，也可以进行签退打卡。
     *
     * @param userId   用户Id
     * @param labelId  签到标签Id
     * @param leaveStr 用户留言
     * @return  用户打卡结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String userClock(Long userId, Long labelId, String leaveStr) {

        // 查询用户的打卡记录（检查用户是否已经在某一位置打卡并且尚未签退）
        List<ClockEnt> clocked = clockDao.listUserClockRecord(userId, ClockStatusEnum.CLOCKED);
        String resultStatus;
        // 当用户此时没有在某一位置打卡并且尚未签退时，可以进行打卡逻辑
        if (CollectionUtils.isEmpty(clocked)) {
            ClockEnt insertBody = new ClockEnt();
            insertBody.setUserId(userId);
            insertBody.setLabelId(labelId);
            insertBody.setGuestbook(leaveStr);
            clockDao.insertClockInfo(insertBody);

            // 标签在线人数加一
            labelDao.addOnlineNum(labelId);
            resultStatus = "OPEN";
        } else {
            ClockEnt clockInfo = clocked.get(0);
            if (labelId.equals(clockInfo.getLabelId())) {
                Integer i = clockDao.updateClockFinish(userId);
                if (i == 1) {

                    // 标签在线人数减一
                    labelDao.cutOnlineNum(labelId);
                    resultStatus = "CLOSE";
                } else {
                    throw new CustomException("数据更新异常");
                }
            } else {
                throw new CustomException("您在" + clockInfo.getLabelInfo().getTitle() + "已经打卡，并且尚未签退");
            }
        }

        // 尝试获取用户尚未完成的并且此时可以完成的签到任务
        List<TaskEnt> couldFinishList = listLabelCouldFinishTask(userId, labelId);
        if (! CollectionUtils.isEmpty(couldFinishList)) {
            List<Long> couldFinishIdList = new LinkedList<>();
            for (TaskEnt one : couldFinishList) {
                couldFinishIdList.add(one.getId());
            }
            Integer influence = taskDao.updateTaskFinish(userId, couldFinishIdList);
            if (influence != couldFinishIdList.size()) {
                throw new CustomException("系统异常");
            }
        }
        return resultStatus;
    }

    /**
     * 用户查询自己的打卡信息
     *
     * @param user        用户Id
     * @param clockStatus 打卡状态
     * @param pageNum     页码号
     * @param pageSize    页容量
     * @return 打卡信息
     */
    @Override
    public List<ClockEnt> listUserClockRecord(Long user, ClockStatusEnum clockStatus, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return clockDao.listUserClockRecord(user, clockStatus);
    }

    /**
     * 查询此时通过标签卡可以完成的签到任务
     *
     * @param userId  用户Id
     * @param labelId 标签卡Id
     * @return 此时通过该标签卡可以完成的签到任务
     */
    @Override
    public List<TaskEnt> listLabelCouldFinishTask(Long userId, Long labelId) {
        // 检查用户指定的签到标签是否存在
        LabelEnt labelEnt = labelDao.getLabelEntById(labelId);
        if (labelEnt == null) {
            throw new CustomException("您指定的签到标签不存在");
        }
        // 尝试获取用户尚未完成的并且此时可以完成的签到任务
        List<TaskEnt> storage = taskDao.listNeedFinishTask(userId);
        List<TaskEnt> couldFinishList = new LinkedList<>();
        if (! CollectionUtils.isEmpty(storage)) {

            // 从这些签到任务中选出可以通过用户指定的签到标签相关的那一部分
            for (TaskEnt one : storage) {
                if (labelId.equals(one.getSignEnt().getLabelId())) {
                    couldFinishList.add(one);
                }
            }
        }
        return couldFinishList;
    }



}
